mem_protect: Add mem_protect support in Juno and FVP for DRAM1
authorRoberto Vargas <[email protected]>
Thu, 3 Aug 2017 08:16:43 +0000 (09:16 +0100)
committerRoberto Vargas <[email protected]>
Mon, 25 Sep 2017 12:32:20 +0000 (13:32 +0100)
mem_protect needs some kind of non-volatile memory because it has
to remember its state across reset and power down events.
The most suitable electronic part for this feature is a NVRAM
which should be only accesible from the secure world. Juno and
FVP lack such hardware and for this reason the MEM_PROTECT
functionality is implemented with Flash EEPROM memory on both
boards, even though this memory is accesible from the non-secure
world. This is done only to show a full implementation of
these PSCI features, but an actual system shouldn't use a
non-secure NVRAM to implement it.

The EL3 runtime software will write the mem_protect flag and BL2
will read and clear the memory ranges if enabled. It is done in
BL2 because it reduces the time that TF needs access to the full
non-secure memory.

The memory layout of both boards is defined using macros which
take different values in Juno and FVP platforms. Generic platform
helpers are added that use the platform specific macros to generate
a mem_region_t that is valid for the platform.

Change-Id: I2c6818ac091a2966fa07a52c5ddf8f6fde4941e9
Signed-off-by: Roberto Vargas <[email protected]>
13 files changed:
include/plat/arm/board/common/board_arm_def.h
include/plat/arm/board/common/v2m_def.h
include/plat/arm/common/plat_arm.h
plat/arm/board/common/board_common.mk
plat/arm/board/common/board_css_common.c
plat/arm/board/fvp/fvp_common.c
plat/arm/board/fvp/fvp_pm.c
plat/arm/board/fvp/sp_min/sp_min-fvp.mk
plat/arm/board/juno/include/platform_def.h
plat/arm/board/juno/sp_min/sp_min-juno.mk
plat/arm/common/arm_bl2_setup.c
plat/arm/common/arm_nor_psci_mem_protect.c [new file with mode: 0644]
plat/arm/css/common/css_pm.c

index 751c3bb10fbd94b3b44aa26248e3dc2de2013289..a065abf5b6757d03a4c8b11b1b55ee157d0f4d88 100644 (file)
 
 #define PLAT_ARM_TRUSTED_SRAM_SIZE     0x00040000      /* 256 KB */
 
+/* Reserve the last block of flash for PSCI MEM PROTECT flag */
 #define PLAT_ARM_FIP_BASE              V2M_FLASH0_BASE
-#define PLAT_ARM_FIP_MAX_SIZE          V2M_FLASH0_SIZE
+#define PLAT_ARM_FIP_MAX_SIZE          (V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
 
 #define PLAT_ARM_NVM_BASE              V2M_FLASH0_BASE
-#define PLAT_ARM_NVM_SIZE              V2M_FLASH0_SIZE
+#define PLAT_ARM_NVM_SIZE              (V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
 
+/* PSCI memory protect definitions:
+ * This variable is stored in a non-secure flash because some ARM reference
+ * platforms do not have secure NVRAM. Real systems that provided MEM_PROTECT
+ * support must use a secure NVRAM to store the PSCI MEM_PROTECT definitions.
+ */
+#define PLAT_ARM_MEM_PROT_ADDR         (V2M_FLASH0_BASE + \
+                                        V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
+
+/*
+ * Map mem_protect flash region with read and write permissions
+ */
+#define ARM_V2M_MAP_MEM_PROTECT                MAP_REGION_FLAT(PLAT_ARM_MEM_PROT_ADDR, \
+                                               V2M_FLASH_BLOCK_SIZE,           \
+                                               MT_DEVICE | MT_RW | MT_SECURE)
 
 #endif /* __BOARD_ARM_DEF_H__ */
index 2ad513acdf0d3675e2cd736c2023612d1e4b0689..364b780375f8982d085cae222c5f7aea149b7175 100644 (file)
@@ -69,6 +69,7 @@
 /* NOR Flash */
 #define V2M_FLASH0_BASE                        0x08000000
 #define V2M_FLASH0_SIZE                        0x04000000
+#define V2M_FLASH_BLOCK_SIZE           0x00040000      /* 256 KB */
 
 #define V2M_IOFPGA_BASE                        0x1c000000
 #define V2M_IOFPGA_SIZE                        0x03000000
index f0e9767819270aae330b9510d9934a9c28f9fe21..4e589c0c817def3d4a20a6ee598803d8d301873f 100644 (file)
@@ -122,6 +122,10 @@ int arm_validate_power_state(unsigned int power_state,
 int arm_validate_ns_entrypoint(uintptr_t entrypoint);
 void arm_system_pwr_domain_resume(void);
 void arm_program_trusted_mailbox(uintptr_t address);
+int arm_psci_read_mem_protect(int *val);
+int arm_nor_psci_write_mem_protect(int val);
+void arm_nor_psci_do_mem_protect(void);
+int arm_psci_mem_protect_chk(uintptr_t base, u_register_t length);
 
 /* Topology utility function */
 int arm_check_mpidr(u_register_t mpidr);
index 46672982c3f3dd65679ae78f12e6529ff03f7961..2023150cc041cd1eb3231e81287f7a86fbe67408 100644 (file)
@@ -12,9 +12,13 @@ PLAT_BL_COMMON_SOURCES       +=      drivers/arm/pl011/${ARCH}/pl011_console.S               \
 
 BL1_SOURCES            +=      plat/arm/board/common/drivers/norflash/norflash.c
 
-BL2_SOURCES            +=      plat/arm/board/common/drivers/norflash/norflash.c
+BL2_SOURCES            +=      lib/utils/mem_region.c                                  \
+                               plat/arm/common/arm_nor_psci_mem_protect.c              \
+                               plat/arm/board/common/drivers/norflash/norflash.c
 
-#BL31_SOURCES          +=
+BL31_SOURCES           +=      lib/utils/mem_region.c                                  \
+                               plat/arm/board/common/drivers/norflash/norflash.c       \
+                               plat/arm/common/arm_nor_psci_mem_protect.c
 
 ifneq (${TRUSTED_BOARD_BOOT},0)
   ifneq (${ARM_CRYPTOCELL_INTEG}, 1)
index 159bf86f41065e29c99136ceb69b2922731a55a8..4638af1836877713ebdfeb492e9341d528e7b984 100644 (file)
@@ -29,6 +29,9 @@ const mmap_region_t plat_arm_mmap[] = {
 const mmap_region_t plat_arm_mmap[] = {
        ARM_MAP_SHARED_RAM,
        V2M_MAP_FLASH0_RO,
+#ifdef PLAT_ARM_MEM_PROT_ADDR
+       ARM_V2M_MAP_MEM_PROTECT,
+#endif
        V2M_MAP_IOFPGA,
        CSS_MAP_DEVICE,
        SOC_CSS_MAP_DEVICE,
@@ -56,6 +59,9 @@ const mmap_region_t plat_arm_mmap[] = {
        ARM_MAP_SHARED_RAM,
        V2M_MAP_IOFPGA,
        CSS_MAP_DEVICE,
+#ifdef PLAT_ARM_MEM_PROT_ADDR
+       ARM_V2M_MAP_MEM_PROTECT,
+#endif
        SOC_CSS_MAP_DEVICE,
        {0}
 };
index e869f5b22e4ffe2beb91e285d28d16bac24df63e..bc033130c3fbd0f513da915e51815d658c224acb 100644 (file)
@@ -109,6 +109,7 @@ const mmap_region_t plat_arm_mmap[] = {
        V2M_MAP_IOFPGA,
        MAP_DEVICE0,
        MAP_DEVICE1,
+       ARM_V2M_MAP_MEM_PROTECT,
        {0}
 };
 #endif
index 9a02089e7a1fd9e750da6223fca9cdb69b6f9ca9..dad3a7949bb3fbf76838c6c871dcb2f91503d130 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -324,5 +324,14 @@ plat_psci_ops_t plat_arm_psci_pm_ops = {
        .system_reset = fvp_system_reset,
        .validate_power_state = arm_validate_power_state,
        .validate_ns_entrypoint = arm_validate_ns_entrypoint,
-       .get_node_hw_state = fvp_node_hw_state
+       .get_node_hw_state = fvp_node_hw_state,
+/*
+ * mem_protect is not supported in RESET_TO_BL31 and RESET_TO_SP_MIN,
+ * as that would require mapping in all of NS DRAM into BL31 or BL32.
+ */
+#if !RESET_TO_BL31 && !RESET_TO_SP_MIN
+       .mem_protect_chk        = arm_psci_mem_protect_chk,
+       .read_mem_protect       = arm_psci_read_mem_protect,
+       .write_mem_protect      = arm_nor_psci_write_mem_protect,
+#endif
 };
index 864df1bad2b6364947754c92d5ab8968da21b6db..b370fd55a7b468ab362d46cde2352fa2c94c638e 100644 (file)
@@ -5,11 +5,14 @@
 #
 
 # SP_MIN source files specific to FVP platform
-BL32_SOURCES           +=      plat/arm/board/fvp/aarch32/fvp_helpers.S        \
+BL32_SOURCES           +=      lib/utils/mem_region.c                          \
+                               plat/arm/board/fvp/aarch32/fvp_helpers.S        \
                                plat/arm/board/fvp/drivers/pwrc/fvp_pwrc.c      \
                                plat/arm/board/fvp/fvp_pm.c                     \
                                plat/arm/board/fvp/fvp_topology.c               \
                                plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c    \
+                               plat/arm/board/common/drivers/norflash/norflash.c       \
+                               plat/arm/common/arm_nor_psci_mem_protect.c      \
                                ${FVP_CPU_LIBS}                                 \
                                ${FVP_GIC_SOURCES}                              \
                                ${FVP_INTERCONNECT_SOURCES}                     \
index f1714e137e8e570fe77dee9226a122da864d4b82..e8a4a40a807538087b1b82639d60f5f2f62788b2 100644 (file)
 
 #ifdef IMAGE_BL2
 #ifdef SPD_opteed
+# define PLAT_ARM_MMAP_ENTRIES         10
+# define MAX_XLAT_TABLES               5
+#else
 # define PLAT_ARM_MMAP_ENTRIES         9
 # define MAX_XLAT_TABLES               4
-#else
-# define PLAT_ARM_MMAP_ENTRIES         8
-# define MAX_XLAT_TABLES               3
 #endif
 #endif
 
@@ -82,8 +82,8 @@
 #endif
 
 #ifdef IMAGE_BL31
-#  define PLAT_ARM_MMAP_ENTRIES                5
-#  define MAX_XLAT_TABLES              2
+#  define PLAT_ARM_MMAP_ENTRIES                6
+#  define MAX_XLAT_TABLES              3
 #endif
 
 #ifdef IMAGE_BL32
index 336c4e7ce2654dc0102a0deba20442bb50ec64e3..cd1f4976c161883c42baa82b2d01fcabebb2d393 100644 (file)
@@ -8,7 +8,10 @@
 BL32_SOURCES   +=      lib/cpus/aarch32/cortex_a53.S           \
                        lib/cpus/aarch32/cortex_a57.S           \
                        lib/cpus/aarch32/cortex_a72.S           \
+                       lib/utils/mem_region.c                  \
+                       plat/arm/board/common/drivers/norflash/norflash.c       \
                        plat/arm/board/juno/juno_topology.c     \
+                       plat/arm/common/arm_nor_psci_mem_protect.c      \
                        plat/arm/soc/common/soc_css_security.c  \
                        ${JUNO_GIC_SOURCES}                     \
                        ${JUNO_INTERCONNECT_SOURCES}            \
index cab6113e9da732b8a5a4c2836a0a9b615da63174..5d83118a8030efd09c601a8d0d4702f91532adee 100644 (file)
@@ -193,6 +193,10 @@ void arm_bl2_platform_setup(void)
 {
        /* Initialize the secure environment */
        plat_arm_security_setup();
+
+#if defined(PLAT_ARM_MEM_PROT_ADDR)
+       arm_nor_psci_do_mem_protect();
+#endif
 }
 
 void bl2_platform_setup(void)
diff --git a/plat/arm/common/arm_nor_psci_mem_protect.c b/plat/arm/common/arm_nor_psci_mem_protect.c
new file mode 100644 (file)
index 0000000..0f16e35
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <mmio.h>
+#include <norflash.h>
+#include <plat_arm.h>
+#include <platform_def.h>
+#include <psci.h>
+#include <utils.h>
+
+mem_region_t arm_ram_ranges[] = {
+       {ARM_NS_DRAM1_BASE, ARM_NS_DRAM1_SIZE},
+};
+
+/*******************************************************************************
+ * Function that reads the content of the memory protect variable that
+ * enables clearing of non secure memory when system boots. This variable
+ * should be stored in a secure NVRAM.
+ ******************************************************************************/
+int arm_psci_read_mem_protect(int *enabled)
+{
+       int tmp;
+
+       tmp = *(int *) PLAT_ARM_MEM_PROT_ADDR;
+       *enabled = (tmp == 1);
+       return 0;
+}
+
+/*******************************************************************************
+ * Function that writes the content of the memory protect variable that
+ * enables overwritten of non secure memory when system boots.
+ ******************************************************************************/
+int arm_nor_psci_write_mem_protect(int val)
+{
+       int enable = (val != 0);
+
+       if (nor_unlock(PLAT_ARM_MEM_PROT_ADDR) != 0) {
+               ERROR("unlocking memory protect variable\n");
+               return -1;
+       }
+
+       if (enable) {
+               /*
+                * If we want to write a value different than 0
+                * then we have to erase the full block because
+                * otherwise we cannot ensure that the value programmed
+                * into the flash is going to be the same than the value
+                * requested by the caller
+                */
+               if (nor_erase(PLAT_ARM_MEM_PROT_ADDR) != 0) {
+                       ERROR("erasing block containing memory protect variable\n");
+                       return -1;
+               }
+       }
+
+       if (nor_word_program(PLAT_ARM_MEM_PROT_ADDR, enable) != 0) {
+               ERROR("programming memory protection variable\n");
+               return -1;
+       }
+       return 0;
+}
+
+/*******************************************************************************
+ * Function used for required psci operations performed when
+ * system boots
+ ******************************************************************************/
+void arm_nor_psci_do_mem_protect(void)
+{
+       int enable;
+
+       arm_psci_read_mem_protect(&enable);
+       if (!enable)
+               return;
+       INFO("PSCI: Overwritting non secure memory\n");
+       clear_mem_regions(arm_ram_ranges, ARRAY_SIZE(arm_ram_ranges));
+       arm_nor_psci_write_mem_protect(0);
+}
+
+/*******************************************************************************
+ * Function that checks if a region is protected by the memory protect
+ * mechanism
+ ******************************************************************************/
+int arm_psci_mem_protect_chk(uintptr_t base, u_register_t length)
+{
+       return mem_region_in_array_chk(arm_ram_ranges,
+                                      ARRAY_SIZE(arm_ram_ranges),
+                                      base, length);
+}
index e0e52004d03cc53c153494cc6aec8357e7cd4f53..93d51fe66239091d8ee98afe911e0b6679aae016 100644 (file)
@@ -290,5 +290,14 @@ plat_psci_ops_t plat_arm_psci_pm_ops = {
        .validate_ns_entrypoint = arm_validate_ns_entrypoint,
        .translate_power_state_by_mpidr = css_translate_power_state_by_mpidr,
        .get_node_hw_state      = css_node_hw_state,
-       .get_sys_suspend_power_state = css_get_sys_suspend_power_state
+       .get_sys_suspend_power_state = css_get_sys_suspend_power_state,
+/*
+ * mem_protect is not supported in RESET_TO_BL31 and RESET_TO_SP_MIN,
+ * as that would require mapping in all of NS DRAM into BL31 or BL32.
+ */
+#if defined(PLAT_ARM_MEM_PROT_ADDR) && !RESET_TO_BL31 && !RESET_TO_SP_MIN
+       .mem_protect_chk        = arm_psci_mem_protect_chk,
+       .read_mem_protect       = arm_psci_read_mem_protect,
+       .write_mem_protect      = arm_nor_psci_write_mem_protect,
+#endif
 };